#include <iostream>
#include <stdio.h>

/*
 * 绑定
 */

class Base
{
	public:
		int x;
	public:
		Base() {
			x = 100;
		}

		void function_1() {
			printf("Base:function_1...\n");
		}

		virtual void function_2() {
			printf("Base:function_2...virtual.\n");
		}
};

class Sub : public Base
{
	public:
		int x;
	public:
		Sub() {
			x = 200;
		}

		void function_1() {
			printf("Sub:function_1...\n");
		}

		virtual void function_2() {
			printf("Sub:function_2...virtual.\n");
		}
};

void TestBound(Base * pb)
{
	int n = pb->x;
	printf("0x%x\n", n);

	pb->function_1();
	pb->function_2();
}

int main(int argc, char ** argv)
{
	Base base;
	Sub sub;

	TestBound(&base);
	TestBound(&sub);
	
	return 0;
}

/*
	0x64
	Base:function_1...
	Base:function_2...virtual.

	0x64
	Base:function_1...
	Sub:function_2...virtual.
 */

#if 0

/*
 * 前期绑定
 */
	/* 什么是绑定 */
	绑定就是将函数调用与类地址关联起来。
	就是调用的代码跟真正的函数地址关联到一起的过程称为绑定。

	/* 编译器绑定 */
	函数编译完了调用的函数地址能确定下来称为编译器绑定。
	如果确定不下来，只有真正调用的时候才能确定地址，称为运行时绑定，或者叫动态绑定，或晚绑定。

	普通的函数、数据成员编译完后就确定了地址，即绑定好了。

/* 
 * 多态
 */
	1.只有 virtual 的函数是动态绑定。
	2.动态绑定还有一个名字，多态。


void TestBound(Base * pb)
{
    11c9:	f3 0f 1e fa          	endbr64 
    11cd:	55                   	push   %rbp
    11ce:	48 89 e5             	mov    %rsp,%rbp
    11d1:	48 83 ec 20          	sub    $0x20,%rsp
    11d5:	48 89 7d e8          	mov    %rdi,-0x18(%rbp)	// tish 指针
	int n = pb->x;
    11d9:	48 8b 45 e8          	mov    -0x18(%rbp),%rax	// tish 指针
    11dd:	8b 40 08             	mov    0x8(%rax),%eax
    11e0:	89 45 fc             	mov    %eax,-0x4(%rbp)	// x 能确定就是base的。
	printf("0x%x\n", n);
    11e3:	8b 45 fc             	mov    -0x4(%rbp),%eax
    11e6:	89 c6                	mov    %eax,%esi
    11e8:	48 8d 3d 5e 0e 00 00 	lea    0xe5e(%rip),%rdi        # 204d <_ZStL19piecewise_construct+0x49>
    11ef:	b8 00 00 00 00       	mov    $0x0,%eax
    11f4:	e8 97 fe ff ff       	callq  1090 <printf@plt>

	pb->function_1();
    11f9:	48 8b 45 e8          	mov    -0x18(%rbp),%rax		// tish 指针
    11fd:	48 89 c7             	mov    %rax,%rdi
    1200:	e8 11 01 00 00       	callq  1316 <_ZN4Base10function_1Ev>	// 直接调用，function_1 能确定就是base的。
	pb->function_2();
    1205:	48 8b 45 e8          	mov    -0x18(%rbp),%rax	// tish 指针
    1209:	48 8b 00             	mov    (%rax),%rax		// 虚表地址
    120c:	48 8b 10             	mov    (%rax),%rdx		// 虚表里的第一个值
    120f:	48 8b 45 e8          	mov    -0x18(%rbp),%rax	// tish 指针
    1213:	48 89 c7             	mov    %rax,%rdi
    1216:	ff d2                	callq  *%rdx				// 间接调用，function_2 不能确定地址。动态绑定
}
    1218:	90                   	nop
    1219:	c9                   	leaveq 
    121a:	c3                   	retq   

#endif
